package com.example.financeapi.utils;

import com.alibaba.fastjson.JSONObject;
import com.example.financeapi.config.constant.APIConstant;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;

/**
 * map工具类
 * @author Alvin
 */
@Slf4j
public class MapUtils {
    /**
     * 根据map的key排序
     * @param map 待排序的map
     * @param isDesc 是否降序，true：降序，false：升序
     * @return 排序好的map
     * @author Alvin
     */
    public static <K extends Comparable<? super K>, V> Map<K, V> sortByKey(Map<K, V> map, boolean isDesc) {
        Map<K, V> result = Maps.newLinkedHashMap();
        if (isDesc) {
            map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByKey().reversed())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        } else {
            map.entrySet().stream().sorted(Map.Entry.comparingByKey())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        }
        return result;
    }

    /**
     * 根据map的value排序
     * @param map 待排序的map
     * @param isDesc 是否降序，true：降序，false：升序
     * @return 排序好的map
     * @author Alvin
     */
    public static <K, V extends Comparable<? super V>> Map<K, V> sortByValue(Map<K, V> map, boolean isDesc) {
        Map<K, V> result = Maps.newLinkedHashMap();
        if (isDesc) {
            map.entrySet().stream().sorted(Map.Entry.<K, V>comparingByValue().reversed())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        } else {
            map.entrySet().stream().sorted(Map.Entry.comparingByValue())
                    .forEachOrdered(e -> result.put(e.getKey(), e.getValue()));
        }
        return result;
    }


    /**
     * Baidu地图通过地址获取经纬度
     */
    public static Map<String, Object> getLngAndLat(String address) {
        String json ="";
        Map<String, Object> map = new HashMap<String, Object>();
        if(StringUtils.isEmpty(address)){
            return map;
        }
        address = address.replace(" ", "");
        String url = String.format(APIConstant.BAIDUMAP_LNGLAT_URL, address,APIConstant.BAIDUMAP_AK);
        try {
            json = loadJSON(url);
            json = json.replace("showLocation&&showLocation(", "");
            if(StringUtils.isNotBlank(json)){
                String endJson =json.substring(json.length()-1, json.length());
                if(")".equals(endJson)){
                    json = json.substring(0, json.length() - 1);
                }
                JSONObject obj = JSONObject.parseObject(json);
                if(obj != null){
                    if ("0".equals(obj.get("status")+"")) {
                        double lng = obj.getJSONObject("result").getJSONObject("location").getDouble("lng");
                        double lat = obj.getJSONObject("result").getJSONObject("location").getDouble("lat");
                        map.put("longitude", lng);
                        map.put("latitude", lat);
                    }else{
                        log.error("未找到相匹配的经纬度，请检查地址！json={},url={},address ={}",json,url,address);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取经纬度错误！程序异常！address={},json ={},msg={},e={}",address,json,e.getMessage(),e);
        }
        return map;
    }


    /**
     * Gade地图根据地址获取高德经纬度
     * @param address
     * @return
     */
    public static String getGaoDeLngAndLat(String address) {
        String result ="";
        if(StringUtils.isEmpty(address)){
            return "";
        }
        address = address.replace(" ", "");
        String url = String.format(APIConstant.GAODEMAP_LNGLAT_URL,APIConstant.GAODEMAP_AK, address);
        try {
            String json = loadJSON(url);
            log.info("Gade地图根据地址获取高德经纬度:url={}",url);
            if(StringUtils.isNotBlank(json)){
                JSONObject obj = JSONObject.parseObject(json);
                if(obj != null){
                    if ("1".equals(obj.get("status")+"")) {
                        JSONObject geocodes =obj.getJSONArray("geocodes").getJSONObject(0);
                        result =geocodes.get("location") ==null?"":geocodes.get("location").toString();
                    }else{
                        log.error("未找到相匹配的经纬度，请检查地址！json={},url={},address ={}",json,url,address);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取经纬度错误！程序异常！address={},msg={},e={}",address,e.getMessage(),e);
        }
        return result;
    }

    /**
     * 请求接口
     * @param url
     * @return
     */
    public static String loadJSON(String url) {
        StringBuilder json = new StringBuilder();
        try {
            URL oracle = new URL(url);
            URLConnection yc = oracle.openConnection();
            BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream(), "UTF-8"));
            String inputLine = null;
            while ((inputLine = in.readLine()) != null) {
                json.append(inputLine);
            }
            in.close();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return json.toString();
    }

    /**
     * 使用高德API接口查询两个地址之间的距离
     * @param startLonLat
     * @param endLonLat
     * @return
     */
    private static Long getDistance(String startLonLat, String endLonLat) {
        //返回起始地startAddr与目的地endAddr之间的距离，单位：米
        Long result = new Long(0);
        String url = String.format(APIConstant.GAODEMAP_DISTANCE_URL, APIConstant.GAODEMAP_AK, startLonLat, endLonLat);
        log.info("Gade地图查询两个地址之间的距离:url={}",url);
        String queryResult = loadJSON(url);
        JSONObject jsonObj = JSONObject.parseObject(queryResult);
        if("1".equals(jsonObj.get("status"))){
            JSONObject results =jsonObj.getJSONArray("results").getJSONObject(0);
            result = Long.parseLong(results.get("distance").toString());
        }
        return result;
    }

    public static void main(String[] args) {

        System.out.println(getLngAndLat("江苏省徐州市睢宁县睢城街道周楼社区"));
        System.out.println(getGaoDeLngAndLat("江苏省徐州市睢宁县睢城街道周楼社区"));

        String start = "上海市青浦区明珠家园5区";
        String end = "江苏省苏州市昆山市昆山南站";
        String startLonLat = getGaoDeLngAndLat(start);
        String endLonLat = getGaoDeLngAndLat(end);
        System.out.println(startLonLat);
        System.out.println(endLonLat);
        Long dis = getDistance(startLonLat,endLonLat);
        System.out.println(dis);
    }

}
